Step 1: Compile & Assemble your C program with ELVM
C code
// You can run a larger C program (FizzBuzz) by changing this condition. // Note you may not want to do this for slower backends (e.g., Brainfuck). #if 1 int putchar(int c); int main() { const char* p = "Hello, world!\n"; for (int i = 0; i < 20; i++) putchar(p[i]); return 0; } #else int putchar(int c); int div(int a, int b){ int result = 0; while(a >= b){ a -= b; result++; } return result; } int mod(int a, int b){ int result = 0; while(a >= b){ a -= b; } return a; } const char* str = "FizzBuzz"; void fizz() { for (int i = 0; i < 4; i++) putchar(str[i]); } void buzz() { for (int i = 4; i < 8; i++) putchar(str[i]); } int isDivisible(int a, int b){ return mod(a, b) == 0; } int printNum(int num){ if(num >= 10){ putchar(48 + div(num, 10)); } putchar(48 + mod(num, 10)); } int main() { for (int i = 1; i <= 10; i++) { int div5 = isDivisible(i, 5); int div3 = isDivisible(i, 3); if(div3 && div5){ fizz(); buzz(); }else if(div3){ fizz(); }else if(div5){ buzz(); }else{ printNum(i); } putchar('\n'); } return 0; } #endif
ELVM IR
"Compile" generates ELVM IR.
"Assemble" assembles IR into prototyping vm instructions. First run can be a bit slow.
Step 1 (alternate): Assemble lower level program
Assembly + Labels
// Store 0 into A IMM 0 0 RES a .L1 // Print some stuff REG a 0 IMM 49 1 ADD PUTC IMM 10 0 PUTC // a++ REG a 0 IMM 1 1 ADD RES a // if a < 12 loop IMM 12 1 LT IMM 1 2 CJMP EXIT
Data (each line is data entry)
Step 2: Validate using JS runtime
Assembled code
JS Runtime output
Program memory size:
-
variables (assemble to update)
Dispatch memory size:
-
variables (assemble to update)
Data memory size:
-
variables (assemble to update) - you may need more for dynamic mem access
Runtime instructions:
-
(run to update)
Runtime memory use:
-
(run to update)
"Run" uses JS-based vm to run the assembled code.
Step 3: Load into figma!!